package cz.tomasdvorak.cars.pages.vehicle;

import cz.tomasdvorak.cars.auth.Auth;
import cz.tomasdvorak.cars.auth.MyAuthenticatedWebSession;
import cz.tomasdvorak.cars.dto.*;
import cz.tomasdvorak.cars.pages.BasePage;
import cz.tomasdvorak.cars.pages.expenses.StatsPage;
import cz.tomasdvorak.cars.utils.Lists;
import cz.tomasdvorak.cars.utils.Maps;
import cz.tomasdvorak.cars.wicket.components.ExternalImageUrl;
import cz.tomasdvorak.cars.wicket.components.auth.MetadataAuthorizationStrategy;
import cz.tomasdvorak.cars.wicket.components.breadcrumbs.BreadcrumbItem;
import cz.tomasdvorak.cars.wicket.components.model.StrModel;
import cz.tomasdvorak.cars.wicket.components.table.AbstractColumnCss;
import cz.tomasdvorak.cars.wicket.components.table.AbstractListDataProvider;
import cz.tomasdvorak.cars.wicket.components.table.EnhancedDataTable;
import cz.tomasdvorak.cars.wicket.components.table.PropertyColumnCss;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.PageParameters;
import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;

import java.util.HashMap;
import java.util.List;

@AuthorizeInstantiation(Auth.USER)
public class AllVehiclesPage extends BasePage {
    private static final int ITEMS_PER_PAGE = 10;

    private class VehiclesProvider extends AbstractListDataProvider<Vehicle> {
        protected List<Vehicle> loadData() throws Exception {
            String sortProperty = null;
            Boolean sortAsc = null;
            SortParam sortParam = getSort();
            if (sortParam != null) {
                sortProperty = sortParam.getProperty();
                sortAsc = sortParam.isAscending();
            }
            VehiclesCriteria criteria = new VehiclesCriteria(sortProperty, sortAsc);
            return AllVehiclesPage.this.getVehiclesDao().getAllVehicles(criteria);
        }
    }

    private class ActionsFragment extends Fragment{

        public ActionsFragment(String id, String markupId, MarkupContainer markupProvider,
                               final IModel<Vehicle> model) {
            super(id, markupId, markupProvider, model);

            final User user = ((MyAuthenticatedWebSession) getSession()).getUser();

            Link editLink = new Link("editLink") {
                public void onClick() {
                    setResponsePage(new VehicleEditingPage(model));
                }
            };
            editLink.setVisible(user.isAdmin() || user.getId() == model.getObject().getOwnerId());
            add(editLink);
            Link deleteLink = new Link("deleteLink") {
                public void onClick() {
                    setResponsePage(new VehicleEditingPage(model));
                }
            };
            MetadataAuthorizationStrategy.authorize(deleteLink, Role.ADMIN.name());

            add(deleteLink);
            Link permissionsLink = new Link("permissionsLink") {
                public void onClick() {
                    HashMap<String, String> params = new Maps.Builder<String, String>().add("id",
                            "" + model.getObject().getId()).toHashMap();
                    setResponsePage(new VehiclePermissionsPage(new PageParameters(params)));
                }
            };

            permissionsLink.setVisible(user.isAdmin() || user.getId() == model.getObject().getOwnerId());
            add(permissionsLink);

            Link expensesLink = new Link("expensesLink") {
                public void onClick() {
                    setResponsePage(new StatsPage(new ExpenseCriteria(null, null, null, model.getObject().getId())));
                }
            };
            add(expensesLink);
        }
    }

    private static final class ThumbFragment extends Fragment {
        private ThumbFragment(String id, String markupId, MarkupContainer markupProvider,
                              IModel<Vehicle> model) {
            super(id, markupId, markupProvider, model);
            add(new ExternalLink("thumbLink", model.getObject().getImageUrl()).add(new ExternalImageUrl("image", model.getObject().getImageThumbUrl())));
        }
    }

    public AllVehiclesPage() {
        IColumn<Vehicle>[] columns = Lists.array(
                new AbstractColumnCss<Vehicle>("col0", new StrModel("")){
                    public void populateItem(Item<ICellPopulator<Vehicle>> cellItem,
                                             String componentId, IModel<Vehicle> rowModel) {
                        cellItem.add(new ThumbFragment(componentId, "thumbFragment", AllVehiclesPage.this, rowModel));
                    }
                },
                new PropertyColumnCss<Vehicle>("col1", new StrModel("manufacturer"), "manufacturer", "manufacturer"),
                new PropertyColumnCss<Vehicle>("col2", new StrModel("model"), "model", "model"),
                new PropertyColumnCss<Vehicle>("col3", new StrModel("registration number"), "registrationNumber", "registrationNumber"),
                new AbstractColumnCss<Vehicle>("col6", new StrModel("type"), "type"){
                    public void populateItem(Item<ICellPopulator<Vehicle>> cellItem,
                                             String componentId, IModel<Vehicle> rowModel) {
                        VehicleBodyType type = rowModel.getObject().getType();
                        IModel<String> model = type != null ? new ResourceModel(
                                "vehicleBodyType." + type.name()) : new Model<String>("");
                        cellItem.add(new Label(componentId, model));
                    }
                },
                new AbstractColumnCss<Vehicle>("col7", new StrModel("")){
                    public void populateItem(Item<ICellPopulator<Vehicle>> cellItem,
                                             String componentId, IModel<Vehicle> rowModel) {
                        cellItem.add(new ActionsFragment(componentId, "actionsFragment", AllVehiclesPage.this, rowModel));
                    }
                }
        );


        VehiclesProvider vehiclesProvider = new VehiclesProvider();
        EnhancedDataTable<Vehicle> table = new EnhancedDataTable<Vehicle>("vehicles", columns,
                vehiclesProvider, ITEMS_PER_PAGE);
        add(table);
        add(new Link("addNewVehicle"){
            public void onClick() {
                setResponsePage(VehicleEditingPage.class);
            }
        });
    }

    protected List<BreadcrumbItem> getPageBreadcrumb() throws Exception {
        return Lists.arrayList(new BreadcrumbItem(new ResourceModel("breadcrumb.knownVehicles")));
    }
}
